<script setup lang='ts' name="admin-role">
import type { VxeGridProps, VxePagerEvents } from 'vxe-table'
import { useRouter } from 'vue-router'
import type { FormInstance } from 'element-plus'
import { SearchForm, SearchTable } from '@fl/components'
import { downloadFile } from '@fl/utils/fn'
import { cloneDeep } from 'lodash-es'
import { nextTick } from 'vue'
import type { Iform, IState } from './types'
import { dialogTitle } from './types'
import { getRoleList, roleStatus, getAddRoleTreeData, getEditRoleTreeData, getRoleDeptTree, addRole, editRole, updateRoleDataScope, deleteRole } from '@fl/api/sys-set-api'

const router = useRouter()
const initialState:IState = {
    roleKey: '', // 权限标识符
    roleName: '',
    status: '',
}

// const plate = ref()
const state = ref(cloneDeep(initialState))
const statusList = [{
    label: '正常',
    value: '0',
}, {
    label: '停用',
    value: '1',
}]

const columns = ref([
    {
        label: '角色名称',
        prop: 'roleName',
        valueType: 'copy',
    },
    {
        label: '权限字符',
        prop: 'roleKey',
        valueType: 'copy',
    },
    {
        label: '状态',
        options: statusList,
        prop: 'status',
        valueType: 'select',
    },
    {
        fieldProps: {
            'endPlaceholder': '结束时间',
            'startPlaceholder': '开始时间',
            'type': 'daterange',
            'value-format': 'YYYY-MM-DD',
        },
        label: '创建时间',
        prop: 'createTime',
        valueType: 'date-picker',
    },
])
const isLoading = ref(false)
const initialPage = {
    currentPage: 1,
    pageSize: 10,
    total: 0,
}
const tablePage = ref(cloneDeep(initialPage))
const gridOptions = reactive<VxeGridProps>({
    columns: [
        { type: 'checkbox', width: 50 },
        { field: 'roleId', minWidth: 90, title: '角色编号' },
        { field: 'roleName', minWidth: 90, title: '角色名称' },
        { field: 'roleKey', minWidth: 80, title: '权限字符' },
        { field: 'roleSort', minWidth: 150, title: '显示顺序' },
        { field: 'status', minWidth: 100, slots: { default: 'status' }, title: '状态' },
        { field: 'createTime', title: '创建时间', width: 300 },
        { fixed: 'right', minWidth: 220, slots: { default: 'operate' }, title: '操作' },
    ],
})
const list = ref([])
const initForm:Iform = {
    dataScope: '2',
    deptIds: [],
    menuCheckStrictly: true,
    menuIds: [],
    remark: '',
    roleId: undefined,
    roleKey: undefined,
    roleName: undefined,
    roleSort: 0,
    status: '0',
}
const formRef = ref()
const form = ref(cloneDeep(initForm))
const rules = {
    roleKey: [
        { message: '权限字符不能为空', required: true, trigger: 'blur' },
    ],
    roleName: [
        { message: '角色名称不能为空', required: true, trigger: 'blur' },
    ],
    roleSort: [
        { message: '角色顺序不能为空', required: true, trigger: 'blur' },
    ],
}
const title = ref('新增角色')
const visible = ref(false)
const menuOptions = ref([])
const menuExpand = ref(false)
const menuNodeAll = ref(false)
const menuTreeRef = ref()
const roleIds = ref('')
const exportUrl = import.meta.env?.DEV ? '/fl/portal-api/system/role/export' : '/portal-api/system/role/export'
const dataScopeOptions = [
    {
        label: '全部数据权限',
        value: '1',
    },
    {
        label: '自定数据权限',
        value: '2',
    },
    {
        label: '本部门数据权限',
        value: '3',
    },
    {
        label: '本部门及以下数据权限',
        value: '4',
    },
    {
        label: '仅本人数据权限',
        value: '5',
    },
]

/**
 * methods start
 */
getListData()

function getListData() {
    getRoleList({
        ...state.value,
        pageNum: tablePage.value.currentPage,
        pageSize: tablePage.value.pageSize,
    }).then((res) => {
        console.log(213232, res)
        list.value = res.rows
        tablePage.value.total = res.total
    })
}

function setStatus(row) {
    const { roleId, status } = row
    roleStatus({
        roleId,
        status,
    }).then((res) => {
        console.log(2333, res)
        ElMessage.success('操作成功')
        getListData()
    }).catch(() => {
        getListData()
    })
}

const handlePageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }) => {
    tablePage.value.currentPage = currentPage
    tablePage.value.pageSize = pageSize
    getListData()
}

function resetSearch() {
    state.value = cloneDeep(initialState)
    getListData()
}

function submitSearch(values) {
    if (values) {
        const { createTime, roleKey, roleName, status } = values
        if (createTime) {
            state.value = {
                params: {
                    beginTime: createTime ? createTime[0] : undefined,
                    endTime: createTime ? createTime[1] : undefined,
                },
                roleKey,
                roleName,
                status,
            }
        }
        else {
            state.value = {
                roleKey,
                roleName,
                status,
            }
        }
        tablePage.value.currentPage = 1
        getListData()
    }
}

// 树权限（展开/折叠）
function handleCheckedTreeExpand(value) {
    for (let i = 0; i < menuOptions.value.length; i++) {
        menuTreeRef.value.store.nodesMap[menuOptions.value[i].id as number].expanded = value
    }
}

// 树权限（全选/全不选）
function handleCheckedTreeNodeAll(value) {
    menuTreeRef.value.setCheckedNodes(value ? menuOptions.value : [])
}
// 树权限（父子联动）
function handleCheckedTreeConnect(value) {
    form.value.menuCheckStrictly = !!value
}

// 所有菜单节点数据
function getMenuAllCheckedKeys() {
    // 目前被选中的菜单节点
    const checkedKeys = menuTreeRef.value.getCheckedKeys()
    // 半选中的菜单节点
    const halfCheckedKeys = menuTreeRef.value.getHalfCheckedKeys()
    checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
    return checkedKeys
}

// 打开弹窗
async function showDialog(type, row) {
    menuNodeAll.value = false
    title.value = type
    const { dataScope, roleId, roleKey, roleName, roleSort, status } = row
    switch (type) {
        case dialogTitle.ADD :
            form.value = cloneDeep(initForm)
            const res = await getAddRoleTreeData()
            menuOptions.value = res
            visible.value = true
            break
        case dialogTitle.EDIT :
            form.value = {
                menuCheckStrictly: true,
                menuIds: [],
                remark: '',
                roleId,
                roleKey,
                roleName,
                roleSort,
                status,
            }
            const menuTreeData = await getEditRoleTreeData(row.roleId)
            menuOptions.value = menuTreeData.menus
            form.value.menuIds = menuTreeData.checkedKeys
            visible.value = true
            nextTick(() => {
                menuTreeData.checkedKeys.forEach((v) => {
                    menuTreeRef.value.setChecked(v, true, false)
                })
            })
            break
        case dialogTitle.CONFIG_PERMISSION :
            form.value = {
                dataScope,
                deptIds: [],
                menuCheckStrictly: true,
                roleId,
                roleKey,
                roleName,
            }
            const deptTreeData = await getRoleDeptTree(roleId)
            menuOptions.value = deptTreeData.depts
            form.value.deptIds = deptTreeData.checkedKeys
            visible.value = true
            nextTick(() => {
                deptTreeData.checkedKeys.forEach((v) => {
                    menuTreeRef.value.setChecked(v, true, false)
                })
            })
            break
    }
}

// 取消按钮
function cancel() {
    visible.value = false
}

// 提交按钮
function submitForm(formEl: FormInstance | undefined) {
    if (!formEl)
        return
    formEl.validate((valid) => {
        if (valid) {
            const { dataScope, remark, roleId, roleKey, roleName, roleSort, status } = form.value
            const params = {
                menuIds: undefined,
                remark,
                roleId,
                roleKey,
                roleName,
                roleSort,
                status,
                deptIds: undefined
            }
            switch (title.value) {
                case dialogTitle.ADD :
                    params.menuIds = getMenuAllCheckedKeys()
                    addRole(params).then(() => {
                        getListData()
                        ElMessage.success('新增成功')
                    })
                    break
                case dialogTitle.EDIT :
                    params.menuIds = getMenuAllCheckedKeys()
                    editRole(params).then(() => {
                        getListData()
                        ElMessage.success('修改成功')
                    })
                    break
                case dialogTitle.CONFIG_PERMISSION :
                    if (dataScope === '2') params.deptIds = getMenuAllCheckedKeys()
                    updateRoleDataScope({
                        dataScope,
                        deptIds: params.deptIds,
                        roleId,
                        roleKey,
                        roleName,
                    }).then(() => {
                        getListData()
                        ElMessage.success('分配成功')
                    })
                    break
            }
            visible.value = false
        }
    })
}

function delRole(row) {
    ElMessageBox.confirm(
        row?.roleId ? `您确定要删除角色『${row.roleName}』吗？` : '您确定要所勾选的角色吗？',
        row?.roleId ? '删除' : '批量删除',
        {
            cancelButtonText: '取消',
            confirmButtonText: '删除',
            type: 'warning',
        },
    )
        .then(() => {
            const params = row?.roleId ?? roleIds.value
            deleteRole(params).then(() => {
                ElMessage.success('删除成功')
                getListData()
            }).catch(() => {
                ElMessage.error('接口请求失败')
            })
        }).catch(() => {
            ElMessage({
                message: '取消删除',
                type: 'info',
            })
        })
}

function checkboxChange(values) {
    const ids = values.records.map(item => item.roleId)
    roleIds.value = ids.join()
}

function toPage(row) {
    router.push({ name: 'role-auth-user', params: { id: row.roleId } })
}

/**
 * methods end
*/
</script>

<template>
    <div class="sys-role">
        <ElCard class="mb-20"
                shadow="never"
        >
            <SearchForm v-bind="state"
                        :columns="columns"
                        submit-text="搜索"
                        @reset="resetSearch"
                        @submit="submitSearch"
            />
        </ElCard>

        <ElCard shadow="never">
            <SearchTable v-bind="gridOptions"
                         v-model:pager="tablePage"
                         :loading="isLoading"
                         :data="list"
                         @page-change="handlePageChange"
                         @checkbox-change="checkboxChange"
            >
                <template #toolbar_buttons>
                    <el-button plain
                               type="primary"
                               @click="showDialog(dialogTitle.ADD, {})"
                    >
                        新增
                    </el-button>

                    <el-button plain
                               type="primary"
                               :disabled="!roleIds"
                               @click="delRole"
                    >
                        批量删除
                    </el-button>

                    <el-button plain
                               type="primary"
                               :disabled="!list.length"
                               @click="downloadFile(exportUrl, 'POST', { 'Content-Type': 'application/json' }, {
                                   ...state,
                                   pageNum: tablePage.currentPage,
                                   pageSize: tablePage.pageSize,
                               }, `role_${new Date().getTime()}.xlsx`)"
                    >
                        导出
                    </el-button>
                </template>

                <template #time="{ row }">
                    {{ row.startTime }} ~ {{ row.endTime }}
                </template>

                <template #status="{ row }">
                    <el-switch v-model="row.status"
                               active-value="0"
                               inactive-value="1"
                               @change="setStatus(row)"
                    />
                </template>

                <template #operate="{ row }">
                    <!-- roleId为1是超级管理员 -->
                    <div class="operate-btns" v-if="row.roleId !== 1">
                        <el-button type="primary"
                                   text
                                   @click="showDialog(dialogTitle.EDIT, row)"
                                   v-hasPermi="['system:role:add']"
                        >
                            编辑
                        </el-button>

                        <el-button type="primary"
                                   text
                                   @click="showDialog(dialogTitle.CONFIG_PERMISSION, row)"
                        >
                            数据权限
                        </el-button>

                        <el-button type="primary"
                                   text
                                   @click="toPage(row)"
                        >
                            分配用户
                        </el-button>

                        <el-button type="default"
                                   text
                                   @click="delRole(row)"
                                   v-hasPermi="['system:role:remove']"
                        >
                            删除
                        </el-button>
                    </div>
                </template>
            </SearchTable>
        </ElCard>
        <!-- 添加或修改角色配置对话框 -->
        <el-dialog v-model="visible"
                   :title="title"
                   width="666px"
        >
            <el-form ref="formRef"
                     class="dialog-form"
                     :model="form"
                     :rules="rules"
                     label-width="100px"
                     label-position="right"
            >
                <el-form-item label="角色名称"
                              prop="roleName"
                >
                    <el-input v-model="form.roleName"
                              :disabled="title === dialogTitle.CONFIG_PERMISSION"
                              placeholder="请输入角色名称"
                    />
                </el-form-item>

                <el-form-item prop="roleKey"
                              class="role-key"
                >
                    <template #label>
                        <el-tooltip content="控制器中定义的权限字符，如：@PreAuthorize(`@ss.hasRole('admin')`)"
                                    placement="top"
                        >
                            <el-icon><QuestionFilled /></el-icon>
                        </el-tooltip>
                        权限字符
                    </template>

                    <el-input v-model="form.roleKey"
                              :disabled="title === dialogTitle.CONFIG_PERMISSION"
                              placeholder="请输入权限字符"
                    />
                </el-form-item>

                <el-form-item v-if="title !== dialogTitle.CONFIG_PERMISSION"
                              label="角色顺序"
                              prop="roleSort"
                >
                    <el-input-number v-model="form.roleSort"
                                     controls-position="right"
                                     :min="0"
                    />
                </el-form-item>

                <el-form-item v-if="title !== dialogTitle.CONFIG_PERMISSION"
                              label="状态"
                >
                    <el-radio-group v-model="form.status">
                        <el-radio v-for="dict in statusList"
                                  :key="dict.value"
                                  :value="dict.value"
                        >
                            {{ dict.label }}
                        </el-radio>
                    </el-radio-group>
                </el-form-item>

                <el-form-item v-if="title === dialogTitle.CONFIG_PERMISSION"
                              label="权限范围"
                >
                    <el-select v-model="form.dataScope">
                        <el-option v-for="item in dataScopeOptions"
                                   :key="item.value"
                                   :label="item.label"
                                   :value="item.value"
                        />
                    </el-select>
                </el-form-item>

                <el-form-item v-show="title !== dialogTitle.CONFIG_PERMISSION || (title === dialogTitle.CONFIG_PERMISSION && !['1', '3', '4', '5'].includes(String(form.dataScope)))"

                              label="菜单权限"
                >
                    <el-checkbox v-model="menuExpand"
                                 @change="handleCheckedTreeExpand"
                    >
                        展开/折叠
                    </el-checkbox>

                    <el-checkbox v-model="menuNodeAll"
                                 @change="handleCheckedTreeNodeAll"
                    >
                        全选/全不选
                    </el-checkbox>

                    <el-checkbox v-model="form.menuCheckStrictly"
                                 @change="handleCheckedTreeConnect"
                    >
                        父子联动
                    </el-checkbox>
                </el-form-item>

                <el-form-item v-show="title !== dialogTitle.CONFIG_PERMISSION || (title === dialogTitle.CONFIG_PERMISSION && !['1', '3', '4', '5'].includes(String(form.dataScope)))"
                              label=""
                >
                    <el-tree ref="menuTreeRef"
                             class="tree-border"
                             :data="menuOptions"
                             show-checkbox
                             node-key="id"
                             :check-strictly="!form.menuCheckStrictly"
                             :props="{
                                 children: 'children',
                                 label: 'label',
                             }"
                    />
                </el-form-item>

                <el-form-item v-if="title !== dialogTitle.CONFIG_PERMISSION"
                              label="备注"
                >
                    <el-input v-model="form.remark"
                              type="textarea"
                              placeholder="请输入内容"
                    />
                </el-form-item>
            </el-form>

            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary"
                               @click="submitForm(formRef)"
                    >
                        确 定
                    </el-button>

                    <el-button @click="cancel">
                        取 消
                    </el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>

<style lang="scss" scoped>
.sys-role {
    .dialog-form {
        height: calc(100vh - 200px);
        overflow-y: auto;
    }

    .dialog-footer {
        display: flex;
        justify-content: end;
        margin-top: 30px;
    }
    :deep(.operate-btns .el-button) {
        margin: 0;
        padding: 6px;
    }
}
</style>
